﻿
var Logic = {

    king: null,

    params: {
        refresh: 60 * 1000
    },

    init: function() {  

        $('.Map').css('cursor', '-moz-grab');
        $('.Tools').sortable({
            items: '> div',
            handle: 'h2',
            distance: 10
        });
        Logic.synchronize(function() {
            Map.init();
            Logic.actions.init();
        });

        $(window).click(function() {
            window.focus();
        });

        $('.TabPane').each(function() {
            $('h2').mousedown(function() {
                var pane = $(this).closest('.TabPane');
                if (!$(this).hasClass('Selected')) {
                    pane.find('.Selected').removeClass('Selected');
                }
                pane.find($(this).attr('target')).addClass('Selected');
            });
        });

        $(document).keydown(function(e) {
            if (e.keyCode == $.ui.keyCode.ESCAPE) {
                $('.Pushed').click();
                $('.Dialog').each(function() {
                    Dialog.close(this);
                });
            }
            if (e.keyCode == $.ui.keyCode.ENTER) {
                $('.Dialog input[type=button]:first').each(function() {
                    if ($(this).is('[disabled]')) {
                        return;
                    }
                    $(this).click();
                });
                return;
            }
            if ($('input:focus').length) {
                return;
            }
            if (e.keyCode == $.ui.keyCode.UP) {
                Map._ground.css('top', parseInt(Map._ground.css('top')) + 10);
                Map.refreshPeriodically();
                return;
            }
            if (e.keyCode == $.ui.keyCode.DOWN) {
                Map._ground.css('top', parseInt(Map._ground.css('top')) - 10);
                Map.refreshPeriodically();
                return;
            }
            if (e.keyCode == $.ui.keyCode.LEFT) {
                Map._ground.css('left', parseInt(Map._ground.css('left')) + 10);
                Map.refreshPeriodically();
                return;
            }
            if (e.keyCode == $.ui.keyCode.RIGHT) {
                Map._ground.css('left', parseInt(Map._ground.css('left')) - 10);
                Map.refreshPeriodically();
                return;
            }
            $('u').each(function() {
                if ($(this).html().charCodeAt(0) == e.keyCode) {
                    $(this).click();
                }
            });
        });
    },

    synchronize: function(onload) {

        $.post('Game/Synchronize', { sessionId: Logic.globals.sessionId }, function(json) {
            Logic.handleSynchronization(json);
            try {
                if (onload) {
                    onload.call(this, json);
                }
            }
            finally {
                setTimeout(function() {
                    Logic.synchronize();
                }, Logic.params.refresh);
            }

        }, 'json');
    },

    handleSynchronization: function(json) {
        try {
            var pos = Tools.point.parse(json.King.Position);
            try {
                Logic.king = {
                    id: json.King.Id,
                    position: pos,
                    squaresNumber: json.King.SquaresNumber,
                    lastKingMoveDate: Tools.date.parse(json.King.LastKingMoveDate),
                    academyTroops: json.King.AcademyTroops,
                    nickname: json.King.Nickname
                };
            }
            catch (e) { }

            try {
                $('.Army .TroopsInAcademy').html(Logic.king.academyTroops);
                $('.Nickname').html(json.King.Nickname);
            }
            catch (e) { }

            if (json.Logs) {
                try {
                    Logic.logs.updateLogs(json.Logs);
                }
                catch (e) {

                }
            }

            if (Map._kingSquare) {
                try {
                    Map.square._refreshPoint(pos.y, pos.x, Map._kingSquare);
                }
                catch (e) { }
            }

            try {
                Logic.actions.sendTroops.refresh();
            }
            catch (e) { }

            if (json.IncomingAttacks) {
                try {
                    Logic.attacks.incoming.refresh(json.IncomingAttacks);
                }
                catch (e) { }
            }

            if (json.OngoingAttacks) {
                try {
                    Logic.attacks.ongoing.refresh(json.OngoingAttacks);
                }
                catch (e) { }
            }


        }
        catch (e) { }
    },

    attacks: {

        incoming: {

            _incomingSquares: {},
            _incomingAttacks: {},

            refresh: function(incomingAttacks) {

                this._incomingAttacks = {};

                var updatingSquares = {};

                for (var i in this._incomingSquares) {
                    var square = this._incomingSquares[i];
                    var x = square.attr('x');
                    var y = square.attr('y');
                    updatingSquares[x + ',' + y] = {
                        x: x,
                        y: y
                    };
                }
                this._incomingSquares = {};

                for (var i in incomingAttacks) {
                    var attack = incomingAttacks[i];
                    attack.Destination = Tools.point.parse(attack.Destination);
                    attack.ArrivalDate = Tools.date.parse(attack.ArrivalDate);
                    var pos = attack.Destination;
                    var key = pos.x + ',' + pos.y;
                    if (!this._incomingAttacks[key]) {
                        this._incomingAttacks[key] = [];
                    }
                    this._incomingAttacks[key].push(attack);
                    updatingSquares[pos.x + ',' + pos.y] = {
                        x: pos.x,
                        y: pos.y
                    };
                }

                for (var i in updatingSquares) {
                    var update = updatingSquares[i];
                    var key = update.x + ',' + update.y;
                    if (Map._loaded[key]) {
                        var square = Map._loaded[key];
                        Map.square._refreshPoint(update.y, update.x, square);
                    }
                }

            }
        },

        ongoing: {

            _ongoingSquares: {},
            _ongoingAttacks: {},

            refresh: function(ongoingAttacks) {

                this._ongoingAttacks = {};

                var updatingSquares = {};

                for (var i in this._ongoingSquares) {
                    var square = this._ongoingSquares[i];
                    var x = square.attr('x');
                    var y = square.attr('y');
                    updatingSquares[x + ',' + y] = {
                        x: x,
                        y: y
                    };
                }
                this._ongoingSquares = {};

                for (var i in ongoingAttacks) {
                    var attack = ongoingAttacks[i];
                    attack.Destination = Tools.point.parse(attack.Destination);
                    attack.ArrivalDate = Tools.date.parse(attack.ArrivalDate);
                    var pos = attack.Destination;
                    var key = pos.x + ',' + pos.y;
                    if (!this._ongoingAttacks[key]) {
                        this._ongoingAttacks[key] = [];
                    }
                    this._ongoingAttacks[key].push(attack);
                    updatingSquares[pos.x + ',' + pos.y] = {
                        x: pos.x,
                        y: pos.y
                    };
                }

                for (var i in updatingSquares) {
                    var update = updatingSquares[i];
                    var key = update.x + ',' + update.y;
                    if (Map._loaded[key]) {
                        var square = Map._loaded[key];
                        Map.square._refreshPoint(update.y, update.x, square);
                    }
                }
            }
        }

    },

    logs: {

        _squareLogs: {},
        _logs: {},

        messages: function(type, name) {
            var a = '';
            switch (type) {
                case 0: a += 'Square lost because of connexity'; break;
                case 1: a += 'Square lost by a direct attack from ' + name; break;
                case 2: a += 'You successfully defended this square against ' + name; break;
                case 3: a += 'Sorry, you attacked ' + (name == null ? 'this' : ('this ' + name + '\'s')) + ' square but you did not win.'; break;
                case 4: a += 'You won this battle, ' + (name == null ? 'this' : ('this ' + name + '\'s')) + ' square is now neutral.'; break;
                case 5: a += 'You won this battle and got ' + (name == null ? 'this' : ('this ' + name + '\'s')) + ' square !'; break;
                case 6: a += 'You lost your previous king, due to ' + name + '. You have a new king.'; break;
                case 7: a += 'Your king has fought a thought battle against' + name + '\'s troops... but he survived.'; break;
                case 8: a += 'You have killed ' + name + '\'s king ! Congratulations !'; break;
                case 9: a += 'You fought ' + name + '\'s king, but he was too strong and you lost the battle.'; break;
                case 10: a += 'You have successfully sent troops in one of your cases.'; break;
                default: a += 'Something funny happened to you. Please email us.';
            }
            return a;
        },

        updateLogs: function(logs) {

            var ol = $('.Logs ol');
            ol.find('li').trigger('mouseout');

            //ol.html( '' );
            for (var i = 0; i < logs.length; i++) {
                var log = logs[i];
                log.Date = Tools.date.parse(log.Date);
                log.Position = Tools.point.parse(log.Position);
                ol.prepend(this.log.create(log));
            }
        },

        log: {

            create: function(log) {
                //var messages = Logic.logs._messages;
            var li = $('<li class="LogKind'+log.Kind+'"></li>');
                li.html('<div class="Date">' + Tools.date.toHuman(log.Date) + '</div><div class="Title">' + Logic.logs.messages(log.Kind, log.OtherKingNickname) + '</div>');
                li.data('log', log);
                li.click(this.click);
                li.hover(this.mouseover, this.mouseout);
                return li;
            },

            mouseover: function() {
                var log = $(this).data('log');
                var pos = log.Position;
                var key = pos.x + ',' + pos.y;
                if (log.over) {
                    return;
                }
                log.over = true;
                if (Map._loaded[key]) {
                    var square = Map._loaded[key];
                    $('.Overlay').show();
                    square.addClass('Hover');
                }
            },

            mouseout: function() {
                var log = $(this).data('log');
                var pos = log.Position;
                if (!log.over) {
                    return;
                }
                log.over = false;
                var key = pos.x + ',' + pos.y;
                if (Map._loaded[key]) {
                    var square = Map._loaded[key];
                    $('.Overlay').hide();
                    square.removeClass('Hover');
                }

            },

            click: function() {
                var log = $(this).data('log');
                var pos = log.Position;
                Map.goToPoint(pos);
            }

        }
    },

    actions: {

        init: function() {
            for( var i in this ) {
           
                if( this[i].init ) {
                    this[i].init();
                }
            }
            /*this.goToKing.init();
            this.moveKing.init();
            this.takeTroops.init();
            this.sendTroops.init();
            this.viewTerritories.init();*/
        },

        goToKing: {

            init: function() {
                $('.Actions .GoToKing').click(function() {
                    Map.goToPoint(Logic.king.position);
                });
            }
        },

        viewTerritories: {

            enabled: false,

            init: function() {
                $('.Actions .ViewTerritories').click(function() {

                    $(this).toggleClass('Pushed');

                    if ($(this).hasClass('Pushed')) {
                        $('.Map').css('cursor', 'help');
                        Logic.actions.viewTerritories.enabled = true;
                    }
                    else {
                        $('.Visible').removeClass('Visible');
                        //$('.Overlay').hide();
                        $('.Map').css('cursor', typeof mozInnerScreenX == 'undefined' ? 'default' : '-moz-grab');
                        Logic.actions.viewTerritories.enabled = false;
                    }
                });
            }
        },

        moveKing: {

            _kingDestinables: [],
            enabled: false,

            init: function() {
                $('.Actions .MoveKing').click(function() {

                    var o = Logic.actions.moveKing;
                    var delay = Logic.globals.moveKingDelay;
                    var movable = new Date().getTime() - Logic.king.lastKingMoveDate.getTime() > delay;

                    if (!$(this).hasClass('Pushed')) {
                        if (!movable) {
                            return;
                        }
                        $('.Actions .Pushed').click();
                        $('.Map').css('cursor', 'crosshair');
                    }
                    else {
                        $('.Map').css('cursor', typeof mozInnerScreenX == 'undefined' ? 'default' : '-moz-grab');
                    }

                    $(this).toggleClass('Pushed');

                    var pos = Logic.king.position;
                    var kingId = Logic.king.id;
                    var keys = [
                        pos.x + ',' + (pos.y - 1),
                        pos.x + ',' + (pos.y + 1),
                        (pos.x - 1) + ',' + pos.y,
                        (pos.x + 1) + ',' + pos.y];

                    while (o._kingDestinables.length) {
                        var square = o._kingDestinables.shift();
                        square.removeClass('KingDestinable');
                    }
                    if ($(this).hasClass('Pushed')) {
                        for (var i = 0; i < keys.length; i++) {
                            var key = keys[i];
                            if (Map._loaded[key]) {
                                var data = Map._data[key];
                                var square = Map._loaded[key];
                                var valid = (data.kingId == kingId);
                                square[valid ? 'addClass' : 'removeClass']('KingDestinable');
                                if (valid) {
                                    o._kingDestinables.push(square);
                                }
                            }
                        }
                    }
                    Logic.actions.moveKing.enabled = $(this).hasClass('Pushed');
                });

                this.refresh();
            },

            refresh: function() {
                var delay = Logic.globals.moveKingDelay;

                var movable = new Date().getTime() - Logic.king.lastKingMoveDate.getTime() > delay;
                if (!movable) {
                    $('.Actions .MoveKing.Pushed').click();
                }

                if (movable) {
                    $('.Army .KingMovement').html('King can move now');
                }
                else {

                    $('.Army .KingMovement').html('Wait ' + Tools.date.toHumanDelay(delay - new Date().getTime() + Logic.king.lastKingMoveDate.getTime()));
                }
                $('.Actions .MoveKing')[movable ? 'slideDown' : 'slideUp']();

                //Logic.actions.moveKing.enabled = $(this).hasClass( 'Pushed' );

                setTimeout(function() {
                    Logic.actions.moveKing.refresh();
                }, 500);
            }

        },
        
        takeTroops: {
        
            init: function() {
                $('.Actions .TakeTroops').click(function() {
                
                    Dialog.displayTroopsTaker();
                });
                
                this.refresh();
            },
            
            refresh: function() {
                var data = Map._kingData;
                var takeable = data && data.troops;
                $('.Actions .TakeTroops')[takeable ? 'slideDown' : 'slideUp']();
            }
        },

        sendTroops: {

            enabled: false,

            init: function() {
                $('.Actions .SendTroops').click(function() {

                    if (!$(this).hasClass('Pushed')) {
                        if (!Logic.king.academyTroops) {
                            return false;
                        }
                        $('.Actions .Pushed').click();
                        $('.Map').css('cursor', 'crosshair');
                    }
                    else {
                        $('.Map').css('cursor', typeof mozInnerScreenX == 'undefined' ? 'default' : '-moz-grab');
                        Logic.actions.sendTroops.path.clear();
                    }
                    $(this).toggleClass('Pushed');
                    Logic.actions.sendTroops.enabled = $(this).hasClass('Pushed');

                    if (Logic.actions.sendTroops.enabled) {
                        if (Map._squareOver) {
                            $(Map._squareOver).mouseover();
                        }
                    }

                    var pos = Logic.king.position;
                    var kingId = Logic.king.id;

                });

                this.refresh();
            },

            refresh: function() {
                var sendable = Logic.king.academyTroops > 0;
                if (!sendable) {
                    $('.Actions .SendTroops.Pushed').click();
                }
                $('.Actions .SendTroops')[sendable ? 'slideDown' : 'slideUp']();
            },

            path: {

                clear: function() {
                    $('.Path').removeClass('Path');
                    $('.Step').remove();
                } /*,
                
                mouseout: function() {
                    Map._squareOver = null;
                    Logic.actions.sendTroops.path.clear();
                },
            
                mouseover: function() {
                    Map._squareOver = this;
                    if( !Logic.actions.sendTroops.enabled ) {
                        return;
                    }
                    var dest = {
                        x : $(this).attr( 'x' ),
                        y : $(this).attr( 'y' )
                    }
                    var key = dest.x + ',' + dest.y;
                    var kingPos = Logic.king.position;
                    
                    $(this).addClass( 'Path' );
                    $(this).append( '<div class="Step"></div' );
                    
                    // If vertical
                    if( kingPos.x == dest.x ) {
                        var incr = dest.y > kingPos.y ? 1 : -1;
                        for( var i = kingPos.y; i!= dest.y; i+= incr ) {
                            var key = kingPos.x + ',' + i;
                            if( Map._loaded[ key ] ) {
                                Map._loaded[ key ].addClass( 'Path' );
                                Map._loaded[ key ].append( '<div class="Step"></div>' );
                            }
                        }
                        return;
                    }
                    
                    // If horizontal
                    if( kingPos.y == dest.y ) {
                        var incr = dest.x > kingPos.x ? 1 : -1;
                        for( var i = kingPos.x; i!= dest.x; i+= incr ) {
                            var key = i + ',' + kingPos.y;
                            if( Map._loaded[ key ] ) {
                                Map._loaded[ key ].addClass( 'Path' );
                                Map._loaded[ key ].append( '<div class="Step"></div>' );
                            }
                        }
                        return;
                    }
                    
                    var lastPos = kingPos;
                    var newPos;
                    
                    if( Math.abs(dest.y - kingPos.y) > Math.abs(dest.x - kingPos.x) ) {               
                        var coeff = (dest.x - kingPos.x - 1)/(dest.y - kingPos.y - 1);
                        var incr = dest.y > kingPos.y ? 1 : -1;
                        
                        var b = kingPos.x + 0.5 - coeff * (kingPos.y + 0.5);
                        for( var i = kingPos.y; i!= dest.y; i+= incr ) {
                            var x = Math.floor(coeff * i + b);
                            var key = x + ',' + i;
                            newPos = { x : x, y : i };
                            if( Map._loaded[ key ] ) {
                                Map._loaded[ key ].addClass( 'Path' );
                                var percent = Math.floor((coeff * i + b - x)*100);
                                Map._loaded[ key ].append( '<div class="Step" style="left: ' + percent + '%"></div>' );
                            }
                            if( newPos.x != lastPos.x ) {
                                var y = newPos.y;
                                var x = coeff * y + b;
                                if( (newPos.x < (x+1)) && (newPos.x >= x) ) {
                                    var key = lastPos.x + ',' + newPos.y;
                                }
                                else {
                                    var key = newPos.x + ',' + lastPos.y;
                                }
                                
                            }
                            lastPos = newPos;
                        }
                        var newPos = dest;
                        if( newPos.x != lastPos.x ) {
                            var y = newPos.y;
                            var x = coeff * y + b;
                            if( (newPos.x < (x+1)) && (newPos.x >= x) ) {
                                var key = lastPos.x + ',' + newPos.y;
                            }
                            else {
                                var key = newPos.x + ',' + lastPos.y;
                            }
                            
                        }
                    }
                    else {
                        var coeff = (dest.y - kingPos.y - 1)/(dest.x - kingPos.x - 1);
                        var incr = dest.x > kingPos.x ? 1 : -1;
                        
                        var b = kingPos.y + 0.5 - coeff * (kingPos.x + 0.5);
                        for( var i = kingPos.x; i!= dest.x; i+= incr ) {
                            var y = Math.floor(coeff * i + b);
   
                            var key = i + ',' + y;
                            newPos = { x : i, y : y };
                            if( Map._loaded[ key ] ) {
                                Map._loaded[ key ].addClass( 'Path' );
                                var percent = Math.floor((coeff * i + b - y)*100);
                                Map._loaded[ key ].append( '<div class="Step" style="top: ' + percent + '%"></div>' );
                            }
                            if( newPos.y != lastPos.y ) {
                                if( incr > 0 ) {
                                    var x = incr ? newPos.x : lastPos.x;
                                }
                                var y = coeff * x + b;
                                
                                if( ((newPos.y+1) > y) && (newPos.y <= y) ) {
                                    var key = lastPos.x + ',' + newPos.y;
                                }
                                else {
                                    var key = newPos.x + ',' + lastPos.y;
                                }
                                
                                Map._loaded[ key ].addClass( 'Path' );
                            }
                            lastPos = newPos;
                        }
                        var newPos = dest;
                        if( newPos.y != lastPos.y ) {
                            if( incr > 0 ) {
                                var x = incr ? newPos.x : lastPos.x;
                            }
                            var y = coeff * x + b;
                            if( ((newPos.y+1) > y) && (newPos.y <= y) ) {
                                var key = lastPos.x + ',' + newPos.y;
                            }
                            else {
                                var key = newPos.x + ',' + lastPos.y;
                            }
                                
                            Map._loaded[ key ].addClass( 'Path' );
                        }
                    }
                }*/
            }
        }
    }
}

$(function() {
    Logic.init();
});